import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router';

import { intersectionWith, isEqual, mergeWith, unionWith } from 'lodash-es';
import { prefixCls } from '@/settings/design-setting';
import qs from 'qs';
import { setToken } from '@/utils/auth';

export const noop = () => {};
type SearchParams = {
  token?: string;
};

export function is(val: unknown, type: string) {
  return toString.call(val) === `[object ${type}]`;
}

export function isObject(val: any): val is Record<any, any> {
  return val !== null && is(val, 'Object');
}

// TODO 此处 isArray 存在歧义
export function isArray(val: any): val is Array<any> {
  return val && Array.isArray(val);
}

/**
 * Add the object as a parameter to the URL
 * @param baseUrl url
 * @param obj
 * @returns {string}
 * eg:
 *  let obj = {a: '3', b: '4'}
 *  setObjToUrlParams('www.baidu.com', obj)
 *  ==>www.baidu.com?a=3&b=4
 */
export function setObjToUrlParams(baseUrl: string, obj: any): string {
  let parameters = '';
  for (const key in obj) {
    parameters += key + '=' + encodeURIComponent(obj[key]) + '&';
  }
  parameters = parameters.replace(/&$/, '');
  return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters;
}

/**
 * Recursively merge two objects.
 * 递归合并两个对象。
 *
 * @param source The source object to merge from. 要合并的源对象。
 * @param target The target object to merge into. 目标对象，合并后结果存放于此。
 * @param mergeArrays How to merge arrays. Default is "replace".
 *        如何合并数组。默认为replace。
 *        - "union": Union the arrays. 对数组执行并集操作。
 *        - "intersection": Intersect the arrays. 对数组执行交集操作。
 *        - "concat": Concatenate the arrays. 连接数组。
 *        - "replace": Replace the source array with the target array. 用目标数组替换源数组。
 * @returns The merged object. 合并后的对象。
 */
export function deepMerge<T extends object | null | undefined, U extends object | null | undefined>(
  source: T,
  target: U,
  mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace'
): T & U {
  if (!target) {
    return source as T & U;
  }
  if (!source) {
    return target as T & U;
  }
  return mergeWith({}, source, target, (sourceValue, targetValue) => {
    if (isArray(targetValue) && isArray(sourceValue)) {
      switch (mergeArrays) {
        case 'union':
          return unionWith(sourceValue, targetValue, isEqual);
        case 'intersection':
          return intersectionWith(sourceValue, targetValue, isEqual);
        case 'concat':
          return sourceValue.concat(targetValue);
        case 'replace':
          return targetValue;
        default:
          throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`);
      }
    }
    if (isObject(targetValue) && isObject(sourceValue)) {
      return deepMerge(sourceValue, targetValue, mergeArrays);
    }
    return undefined;
  });
}

export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized {
  if (!route) return route;
  const { matched, ...opt } = route;
  return {
    ...opt,
    matched: (matched
      ? matched.map((item) => ({
          meta: item.meta,
          name: item.name,
          path: item.path
        }))
      : undefined) as RouteRecordNormalized[]
  };
}

export function setAppUserTokenToSession(): void {
  const { token }: SearchParams = window.location.search
    ? qs.parse(window.location.search.substr(1))
    : {};
  if (token) {
    setToken(token);
  }
}

// 处理单个
export const setRootCss = (property: any, value: any) => {
  document.documentElement.style.setProperty(property, value);
};

// 处理多个全局css属性
export const updateRootCss = (obj: any) => {
  Object.keys(obj).map((key) => {
    setRootCss(key, obj[key]);
  });
};

/**
 * @description: 分隔字符串
 * @param {*} str 需要分隔的原字符串，也可以是数字类型
 * @param {*} splitList 分隔方式的数组，如[3, 4, 4]，或者'4'字符按照每4个字符分隔
 * @param {*} type 以什么字符串进行分隔
 * @return {*} 返回分隔后的字符串
 */
export const splitString = (str: string, split: number[] | number = [], type = ' ') => {
  if (typeof str !== 'string' && typeof str !== 'number') {
    return str;
  }
  const strList = String(str).replace(/\D/g, '').split('');
  const result: string[] = [];
  while (strList.length) {
    const splitNum: number = (Array.isArray(split) ? split.shift() : split)!;
    result.push(strList.splice(0, splitNum || strList.length).join(''));
  }
  return result.join(type);
};

// 金额数字大写 最大15位整数 4位小数
export const amountInWords = (money: string) => {
  //汉字的数字
  const cnNum: string[] = new Array('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖');
  //基本单位
  const cnIntRadices: string[] = new Array('', '拾', '佰', '仟');
  //对应整数部分扩展单位
  const cnIntUnits: string[] = new Array('', '万', '亿', '兆');
  //对应小数部分单位
  const cnDecUnits: string[] = new Array('角', '分', '毫', '厘');
  //整数金额时后面跟的字符
  const cnInteger = '整';
  //整型完以后的单位
  const cnIntLast = '元';
  //最大处理的数字
  const maxNum = 999999999999999.999;
  const minus = '负';
  //金额整数部分
  let integerNum,
    //金额小数部分
    decimalNum,
    //输出的中文金额字符串
    chineseStr = '',
    //分离金额后用的数组，预定义
    parts;
  if (money == '') {
    return '';
  }
  if (money[0] === '-') {
    chineseStr += minus;
    money = money.substr(1);
  }
  const numberMoney = parseFloat(money);
  if (numberMoney >= maxNum) {
    //超出最大处理数字
    return '';
  }
  if (numberMoney === 0) {
    chineseStr = cnNum[0] + cnIntLast + cnInteger;
    return chineseStr;
  }
  //转换为字符串
  const strMoney = money.toString();
  if (strMoney.indexOf('.') == -1) {
    integerNum = strMoney;
    decimalNum = '';
  } else {
    parts = strMoney.split('.');
    integerNum = parts[0];
    decimalNum = parts[1].substring(0, 4);
  }
  //获取整型部分转换
  if (parseInt(integerNum, 10) > 0) {
    let zeroCount = 0;
    const IntLen = integerNum.length;
    for (let i = 0; i < IntLen; i++) {
      const n = integerNum.substring(i, i + 1);
      const p = IntLen - i - 1;
      const q = p / 4;
      const m = p % 4;
      if (n == '0') {
        zeroCount++;
      } else {
        if (zeroCount > 0) {
          chineseStr += cnNum[0];
        }
        //归零
        zeroCount = 0;
        chineseStr += cnNum[parseInt(n)] + cnIntRadices[m];
      }
      if (m == 0 && zeroCount < 4) {
        chineseStr += cnIntUnits[q];
      }
    }
    chineseStr += cnIntLast;
  }
  //小数部分
  if (decimalNum != '') {
    const decLen = decimalNum.length;
    for (let i = 0; i < decLen; i++) {
      const n = decimalNum.substring(i, i + 1);
      if (n != '0') {
        chineseStr += cnNum[Number(n)] + cnDecUnits[i];
      }
    }
  }
  if (chineseStr == '') {
    chineseStr += cnNum[0] + cnIntLast + cnInteger;
  } else if (decimalNum == '') {
    chineseStr += cnInteger;
  }
  return chineseStr;
};

// 获取全局css变量，样式切分用
export const getGlobalCls = (
  scope: string
): {
  prefixCls: string;
} => {
  return {
    prefixCls: `${prefixCls}-${scope}`
  };
};
